Modifying original code
Original file:
Fig3_4_6_ExtFig5-6-10_RPM_RPMA_Allos_CellTag.R Fig3_4_6_ExtFig5-6-10_RPM_RPMA_Allos_CellTag.R
file on GitHub
This notebook is modified from the original code to remove the
preprocessing steps and show figures inline within the notebook.
There is a separate notebook for the CellTag analysis.
Load the Seurat object and CellTag clones
TBO_seurat<-readRDS("../data/05_2025_RPM_RPMA_TBO_CellTag_Seurat_wSigs_FA_dpt_final.rds")
TBO_seurat
An object of class Seurat
110982 features across 26618 samples within 2 assays
Active assay: RNA (55491 features, 0 variable features)
2 layers present: counts, data
1 other assay present: norm
2 dimensional reductions calculated: umap, fa
clones <- readRDS("../data/05_2025_RPM_RPMA_TBOAllo_CellTagClones_Onlyclones.rds")
clones
An object of class Seurat
110982 features across 5965 samples within 2 assays
Active assay: RNA (55491 features, 0 variable features)
2 layers present: counts, data
1 other assay present: norm
2 dimensional reductions calculated: umap, fa
Load organoid data as SingleCellExperiment
sce <- as.SingleCellExperiment(TBO_seurat, assay = "norm")
phenotypes <- as.character(unique(sce@colData@listData$Pheno))
pheno_pairs_list <- combn(phenotypes, 2, simplify = FALSE)
Define color palettes
my_colors <- c(
"#E41A1C", # strong red
"#377EB8", # medium blue
"#4DAF4A", # green
"#984EA3", # purple
"#FF7F00", # orange
"#FFFF33", # yellow
"#A65628", # brown
"#e7298a", # pink
"#666666", # grey
"#66C2A5", # teal
"#FC8D62", # salmon
"#8DA0CB", # soft blue
"#E78AC3", # soft pink (different from 8)
"#A6D854", # light green (but yellowish tint, not green)
"#FFD92F", # lemon yellow
"#E5C494", # light brown
"#B3B3B3", # light grey
"#1B9E77", # deep teal
"#D95F02", # dark orange
"#7570B3", # strong purple
"#66A61E" # olive green (NOT same green as before)
)
Define function to plot violin plots by phenotype
Copied from 02_WT_RPM_Organoids_Allografts_notebook.Rmd
Needs SingleCellExperiment sce object and
pheno_pairs_list defined in the notebook.
plotVlnByPhen <- function(feature, yl=c(-0.1,0.3), focus=NA) {
if(!is.na(focus)) {
pheno_pairs_list <- pheno_pairs_list[sapply(pheno_pairs_list, function(x) focus %in% x)]
}
scater::plotColData(sce, x = "Pheno", y = feature, colour_by = "Pheno") +
scale_discrete_manual(aesthetics = c("colour", "fill"), values=pheno_col) +
theme(axis.title.y = element_text(size = 24), axis.text.y = element_text(size = 16),
axis.text.x = element_blank(), # rotate x-axis labels
plot.title = element_blank(), # remove plot title
legend.position = "none" # remove legend
) + labs(x = "", # custom x-axis title
y = "Signature score" # custom y-axis title
) + ylim(yl[1], yl[2]) +
geom_boxplot(fill=pheno_col, alpha=1/5, position = position_dodge(width = .2),
size=0.2, color="black", notch=TRUE, notchwidth=0.3, outlier.shape = 2, outlier.colour=NA) # +
# stat_summary(fun = mean,
# geom = "point",
# shape = 18,
# size = 2,
# color = "red",
# position = position_dodge(width = 0.5)) +
# ggpubr::stat_compare_means(method = "wilcox.test", label = "p.signif", size=4,
# vjust = 0.5,
# hide.ns = TRUE, comparisons = pheno_pairs_list)
}
Fig. 2e UMAP
DimPlot(TBO_seurat, group.by='Genotype', cols=c("darkorchid4","orange"),
pt.size = 0.1,
reduction='umap', label=FALSE, label.size=7, shuffle=TRUE) & NoAxes()

Fig. 2f (UMAP by Leiden cluster)
DimPlot(TBO_seurat, group.by='leiden_scVI_1.2',
cols=my_colors, reduction='umap', label=TRUE, label.size=5,
pt.size = 0.1) & NoAxes() +
theme(legend.position="none")

Idents(TBO_seurat) <- 'leiden_scVI_1.2'
x <- table(TBO_seurat@meta.data$Genotype,Idents(TBO_seurat))
proportions <- as.data.frame(100*prop.table(x, margin = 1))
colnames(proportions) <- c("Sample", "Cluster", "Frequency")
# ggpubr::ggbarplot(proportions, x="Sample", y="Frequency", fill = "Sample", group = "Sample",
# ylab = "Frequency (percent)", xlab="Phase", palette =c("indianred3","green3","royalblue4")) +
# theme_bw() + facet_wrap(facets = "Cluster", scales="free_y", ncol =4) +
# theme(axis.text.y = element_text(size=6)) + ggpubr::rotate_x_text(angle = 45)
Fig 2f
# Stacked
p <- ggplot(proportions, aes(fill=Cluster, y=Frequency, x=Sample)) +
geom_bar(position="stack", stat="identity")
p + scale_fill_manual(values=my_colors) + theme_bw() +
theme(axis.text.y = element_text(size=16),
axis.text.x = element_text(size=16, angle = 90, vjust = 0.5, hjust=1),
axis.title.x = element_text(size=16), axis.title.y = element_text(size=16),
legend.text = element_text(size=12), legend.title = element_blank()) +
labs(x = NULL, y = "Sample composition (%)")

Fig. 2h
UMAP colored by SCLC fate
# Define fate color vector and use to plot by cell state
pheno_col <- c("brown2","darkorchid4","dodgerblue","#66A61E","orange","turquoise4","turquoise")
DimPlot(TBO_seurat, group.by='Pheno', cols=pheno_col, reduction='umap', label=FALSE,
shuffle=TRUE, label.size=6) & NoAxes()

Fig. 2h (stacked barplot by Pheno)
Idents(TBO_seurat) <-'Pheno'
x <- table(TBO_seurat@meta.data$Genotype,Idents(TBO_seurat))
proportions <- as.data.frame(100*prop.table(x, margin = 1))
colnames(proportions)<-c("Cluster", "Sample", "Frequency")
p <- ggplot(proportions, aes(fill=Sample, y=Frequency, x=Cluster)) +
geom_bar(position="stack", stat="identity")
p + scale_fill_manual(values=pheno_col) + theme_bw() +
theme(axis.text.y = element_text(size=20),
axis.text.x=element_text(size=20, angle = 90, hjust = 1, vjust = 0.5),
axis.title.x = element_text(size=20), axis.title.y = element_text(size=20),
legend.text = element_text(size=20), legend.title = element_text(size=20)) +
labs(x = NULL)

Fig. 2i UMAP
NE score (correlation)
FeaturePlot(TBO_seurat, features = c("NE_spearman"), pt.size=0.2,
reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

Fig 2i (violin plots of NE score by SCLC fate)
plotVlnByPhen("NE_spearman", yl=c(-.7, .8))

Fig 2i (violin plots of NE score by genotype)
x <- scater::plotColData(sce, x = "Genotype", y = "NE_spearman", colour_by = "Genotype") +
scale_discrete_manual(aesthetics = c("colour", "fill"), values=c("darkorchid4","orange"))
x <- x + theme(axis.title.y = element_text(size = 24),axis.text.y = element_text(size = 16),
axis.text.x = element_blank(),
# plot.title = element_blank(),
legend.position = "none") + labs(x = "", y = "Signature score") + ylim(-1,1) +
geom_boxplot(fill=c("darkorchid4","orange"), alpha=1/5,
position = position_dodge(width = .2), size=0.2,
color="black", notch=TRUE, notchwidth=0.3, outlier.shape = 2, outlier.colour=NA)
## Perform wilcoxon rank-sum test for RPM vs RPMA on the NE score data (Fig. 3i) ##
x + stat_summary(fun = mean,
geom = "point",
shape = 18,
size = 2,
color = "red",
position = position_dodge(width = 0.9)) +
ggpubr::stat_compare_means(method = "wilcox.test",label = "p.signif",
hide.ns = TRUE,comparisons = list(c("RPM", "RPMA")))

Fig. 2j
Fig 2j (UMAP marker gene expression)
Equivalent color schemes:
*
viridis::scale_color_viridis(option="rocket", direction=-1)
*
scale_color_gradientn(colors=viridis::rocket(10, direction=-1))
# TF target gene scores in UMAP
FeaturePlot(TBO_seurat, features = c("ASCL1_Targets1"), pt.size=0.2,
reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

FeaturePlot(TBO_seurat, features = c("NEUROD1_Targets1"), pt.size=0.2,
reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

FeaturePlot(TBO_seurat, features = c("ATOH1_Targets1"), pt.size=0.2,
reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

FeaturePlot(TBO_seurat, features = c("POU2F3_Targets1"), pt.size=0.2,
reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

FeaturePlot(TBO_seurat, features = c("YAP_Activity1"), pt.size=0.2,
reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

VlnPlots by genotype with wilcoxon rank sum tests
Fig. 2j (violin plots)
plotTFscoresVln <- function(score_name, yl=c(-.1, .32)) {
a <- VlnPlot(TBO_seurat,
features = c(score_name),
group.by = "Genotype",
cols = c("darkorchid4", "orange"),
pt.size = 0.01,
alpha = 0.05,
ncol = 1) +
theme(axis.title.y = element_text(size = 20),
axis.text.x = element_text(angle = 0, hjust = 0.5, size=20), # rotate x-axis labels
# plot.title = element_blank(), # remove plot title
legend.position = "none" # remove legend
) +
labs(x = "", # custom x-axis title
y = "Expression" # custom y-axis title
) + ylim(yl[1], yl[2]) +
stat_summary(fun = mean,
geom = "point",
shape = 18,
size = 2,
color = "red",
position = position_dodge(width = 0.9)) +
ggpubr::stat_compare_means(method = "wilcox.test", label = "p.signif", size=8,
hide.ns = TRUE, comparisons = list(c("RPM", "RPMA")))
# Add mean point and do wilcoxon rank sum test
return(a)
}
Fig 2j (insets)
plotTFscoresVln("ATOH1_Targets1")

plotTFscoresVln("ASCL1_Targets1", yl=c(-0.1, 0.8))

plotTFscoresVln("NEUROD1_Targets1")

plotTFscoresVln("POU2F3_Targets1")

plotTFscoresVln("YAP_Activity1", yl=c(-0.1, 1))

Fig. 2k (UMAP by cell type consensus signature)
FeaturePlot(TBO_seurat, features = c("NE_Consensus1"), pt.size=0.2,
reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

FeaturePlot(TBO_seurat, features = c("Basal_Consensus1"), pt.size=0.2,
reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

FeaturePlot(TBO_seurat, features = c("Tuft_Consensus1"), pt.size=0.2,
reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

Fig. 2k (violin plots of consensus signatures by SCLC fate)
plotVlnByPhen("NE_Consensus1", yl=c(-0.5, 1.3))

plotVlnByPhen("Tuft_Consensus1", yl=c(-0.25, 1))

plotVlnByPhen("Basal_Consensus1", yl=c(-0.1, 1.1))

Fig 2l (violin plots of SCLC arhcetype scores by phenotype)
plotVlnByPhen("A_Archetype1", yl=c(-0.05, 0.27))

plotVlnByPhen("A2_Archetype1", yl=c(-0.05, 0.2))

plotVlnByPhen("N_Archetype1", yl=c(0, 0.3))

plotVlnByPhen("P_Archetype1", yl=c(0, 0.27))

Ext Data Fig 5c
plotStackedBarByGeno <- function(gene, lab) {
dat <- FetchData(TBO_seurat, vars = c(gene, "Genotype"))
dat <- dat %>%
mutate(Expression_Status = ifelse(dat[,gene] > 0.01, "Positive", "Negative"))
x <- table(dat$Genotype, dat$Expression_Status)
proportions <- as.data.frame(prop.table(x, margin = 1))
colnames(proportions) <- c("Cluster", "Sample", "Fraction")
p <- ggplot(proportions, aes(fill = Sample, y = Fraction, x = Cluster)) +
geom_bar(position = "stack", stat = "identity")
p <- p + scale_fill_manual(values=c("blue4","red3"))+ theme_bw() +
theme(axis.text.y = element_text(size=20), axis.text.x=element_text(size=20),
axis.title.x =element_text(size=20), axis.title.y = element_text(size=20),
legend.text = element_text(size=20), legend.title = element_text(size=0),
plot.title = element_text(size = 18, face = "plain", hjust = 0.5)) +
labs(y = lab, x = NULL)
return(p)
}
plotStackedBarByGeno("Ascl1", "Fraction of Ascl1-hi cells (>0.01)")

plotStackedBarByGeno("Neurod1", "Fraction of Neurod1-hi cells (>0.01)")

plotStackedBarByGeno("Pou2f3", "Fraction of Pou2f3-hi cells (>0.01)")

Extended Data Fig. 5e
Violin plots of expression of TFs by Leiden cluster
genes <- c("Ascl1","Neurod1","Pou2f3")
# Create violin plots with Kruskal-Wallis test
plots <- lapply(genes, function(gene) {
p <- VlnPlot(TBO_seurat,
features = gene,
group.by = "leiden_scVI_1.2",
cols = my_colors,
alpha = 0.5) + # smaller dots
ggpubr::stat_compare_means(method = "kruskal.test",
label = "p.format",
label.x = 2,size = 5) +
ggtitle("") +
theme(plot.title = element_text(face = "italic"), legend.position = "none", # Remove legend
axis.title.x = element_blank(),axis.title.y = element_text(size = 20),
axis.text.y = element_text(size = 20), axis.text.x = element_text(size = 14)) + # Remove x-axis label
labs(y = "Expression") # Change y-axis label to "Expression"
return(p)
})
# Arrange plots
patchwork::wrap_plots(plots, ncol = 3)

Ext Data Fig 10
FeaturePlot(TBO_seurat, features = c("Iono_Mouse_Ext1"), pt.size=0.2,
reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

FeaturePlot(TBO_seurat, features = c("Iono_Human1"), pt.size=0.2,
reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

Ext Data Fig. 10e (violin plots of consensus signatures by SCLC
fate)
plotVlnByPhen("Iono_Mouse_Ext1", yl=c(-0.1, 0.45))

plotVlnByPhen("Iono_Human1", yl=c(-0.1, .75))

Fig 5d
Caris SCLC tumor signatures in basal cells
caris_feat <- c("Caris_A1","Caris_Y1","Caris_N1","Caris_Mixed1","Caris_P1","Caris_TN-1")
v <- FeaturePlot(TBO_seurat, features = caris_feat, pt.size=0.2, reduction='umap')
v <- lapply(v, `+`, scale_color_viridis(option="rocket", direction=-1))
lapply(v, `+`, NoAxes())
[[1]]
[[2]]
[[3]]
[[4]]
[[5]]
[[6]]






Fig 5d (violin plots of human tumor SCLC scores by SCLC fate)
plotVlnByPhen("Caris_A1", yl=c(-0.1, 0.2))

plotVlnByPhen("Caris_Y1", yl=c(-0.1, 0.2))

plotVlnByPhen("Caris_N1", yl=c(-0.1, 0.3))

plotVlnByPhen("Caris_Mixed1", yl=c(-0.1, 0.15))

plotVlnByPhen("Caris_P1", yl=c(-0.1, 0.25))

plotVlnByPhen("Caris_TN.1", yl=c(-0.1, 0.25))

Fig. 5e
Gene signature scores correlation heatmap
signature_matrix <- FetchData(TBO_seurat, vars = c("Caris_A1", "George_A1", "Liu_A1","Lissa_A1","ASCL1_Targets1",
"Caris_N1","George_N1", "Liu_N1","Lissa_N1", "NEUROD1_Targets1",
"Caris_P1","George_P1", "Liu_P1","POU2F3_Targets1",
"Caris_Y1","George_Y1", "Lissa_Y1", "YAP_Activity1",
"Gay_SCLC-I1","MHC_Sig_Gay1",
"NE_Consensus1","Basal_Consensus1","Tuft_Consensus1"))
# T_Cell_Inflamed_Gay1
# Compute Pearson correlation matrix
correlation_matrix <- cor(signature_matrix, method = "pearson")
# Define color scale from -1 to 1
breaks_seq <- seq(-1, 1, length.out = 100) # Ensure scale covers full correlation range
pheatmap::pheatmap(correlation_matrix,
color = scico::scico(100, palette = "berlin"),
display_numbers = FALSE,
breaks = breaks_seq, number_color = "gray80",fontsize_number=6,
main = "Signature correlation in mouse TBO Allografts", cluster_cols = TRUE, cluster_rows=TRUE)

Fig 5g
Inflammatory signatures in basal cells
# Fig 5g feature plot (MHC_Sig_Gay1="Antigen presentation") #
FeaturePlot(TBO_seurat, features = c("MHC_Sig_Gay1"), pt.size=0.2,
reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

### NMF3-I signature for Fig. 5g
FeaturePlot(TBO_seurat, features = c("NMF3-I1"), pt.size=0.2,
reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

### Gay et al SCLC-I signature for Fig. 5g
FeaturePlot(TBO_seurat, features = c("Gay_SCLC-I1"), pt.size=0.2,
reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

Fig 5g (violin plots of inflammation scores by SCLC fate)
plotVlnByPhen("MHC_Sig_Gay1", yl=c(-0.1, 0.8))

plotVlnByPhen("NMF3.I1", yl=c(-0.1, 0.5))

plotVlnByPhen("Gay_SCLC.I1", yl=c(-0.1, 0.3))

Fig 5h (violin plots of therapeutic target gene expression by SCLC
fate)
x_labs <- c("A","A/N","N","At","P","SL","B")
v <- VlnPlot(TBO_seurat, features = c("Dll3", "Ncam1", "Sez6", "Tacstd2"),
group.by=c("Pheno"), cols=pheno_col,alpha=0.05, ncol=4)
v <- lapply(v, `+`, labs(x=NULL, y="Expression"))
v <- lapply(v, `+`, theme(axis.text.x = element_text(angle=90)))
v <- lapply(v, `+`, scale_x_discrete(labels=x_labs))
patchwork::wrap_plots(v, ncol=4)

Ext Data Fig 6a
DimPlot(TBO_seurat, group.by='GenoCT', cols=my_colors, shuffle=TRUE,
reduction='umap', label=FALSE, label.size=6) & NoAxes() + NoLegend()

DimPlot(TBO_seurat, group.by='GenoCT', cols=my_colors, shuffle=TRUE,
reduction='fa', label=FALSE, label.size=6) & NoAxes() + NoLegend()

CellTag analysis in other notebook
LS0tCnRpdGxlOiAiUlBNIFJQTUEgQWxsb3Mgbm90ZWJvb2siCmF1dGhvcjogIkFiYmllIElyZWxhbmQsIERhcnJlbiBUeXNvbiIKZGF0ZTogIjIwMjUtMDYtMjQiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCiMjIyBNb2RpZnlpbmcgb3JpZ2luYWwgY29kZQpPcmlnaW5hbCBmaWxlOiBgRmlnM180XzZfRXh0RmlnNS02LTEwX1JQTV9SUE1BX0FsbG9zX0NlbGxUYWcuUmAgCltGaWczXzRfNl9FeHRGaWc1LTYtMTBfUlBNX1JQTUFfQWxsb3NfQ2VsbFRhZy5SIGZpbGUgb24gR2l0SHViXShodHRwczovL2dpdGh1Yi5jb20vVEdPbGl2ZXItbGFiL0lyZWxhbmRfQmFzYWxfU0NMQ18yMDI1L2Jsb2IvbWFpbi9SX0NvZGUvRmlnM180XzZfRXh0RmlnNS02LTEwX1JQTV9SUE1BX0FsbG9zX0NlbGxUYWcuUikgIAoKVGhpcyBub3RlYm9vayBpcyBtb2RpZmllZCBmcm9tIHRoZSBvcmlnaW5hbCBjb2RlIHRvIHJlbW92ZSB0aGUgcHJlcHJvY2Vzc2luZyBzdGVwcyAKYW5kIHNob3cgZmlndXJlcyBpbmxpbmUgd2l0aGluIHRoZSBub3RlYm9vay4gICAgCgpUaGVyZSBpcyBhIHNlcGFyYXRlIG5vdGVib29rIGZvciB0aGUgQ2VsbFRhZyBhbmFseXNpcy4KCiMjIyBSZWxhdGVkIHRvOgoqIEZpZyAyZS1sCiogRmlnIDVkLWgKKiBFeHRlbmRlZCBEYXRhIEZpZyA1YyxlCiogRXh0ZW5kZWQgRGF0YSBGaWcgNmEKKiBFeHRlbmRlZCBEYXRhIEZpZyAxMGUKCmBgYHtyfQpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMoewogICAgbGlicmFyeShTZXVyYXQpCiAgICBsaWJyYXJ5KFNldXJhdE9iamVjdCkKICAgIGxpYnJhcnkoU3VtbWFyaXplZEV4cGVyaW1lbnQpCiAgICBsaWJyYXJ5KGdncGxvdDIpCiAgICBsaWJyYXJ5KGdncHVicikKfSkKYGBgCgojIyMgTG9hZCB0aGUgU2V1cmF0IG9iamVjdCBhbmQgQ2VsbFRhZyBjbG9uZXMKYGBge3J9ClRCT19zZXVyYXQ8LXJlYWRSRFMoIi4uL2RhdGEvMDVfMjAyNV9SUE1fUlBNQV9UQk9fQ2VsbFRhZ19TZXVyYXRfd1NpZ3NfRkFfZHB0X2ZpbmFsLnJkcyIpClRCT19zZXVyYXQKCmNsb25lcyA8LSByZWFkUkRTKCIuLi9kYXRhLzA1XzIwMjVfUlBNX1JQTUFfVEJPQWxsb19DZWxsVGFnQ2xvbmVzX09ubHljbG9uZXMucmRzIikKY2xvbmVzCmBgYAojIyMgTG9hZCBvcmdhbm9pZCBkYXRhIGFzIFNpbmdsZUNlbGxFeHBlcmltZW50CmBgYHtyfQpzY2UgPC0gYXMuU2luZ2xlQ2VsbEV4cGVyaW1lbnQoVEJPX3NldXJhdCwgYXNzYXkgPSAibm9ybSIpCmBgYAoKYGBge3J9CnBoZW5vdHlwZXMgPC0gYXMuY2hhcmFjdGVyKHVuaXF1ZShzY2VAY29sRGF0YUBsaXN0RGF0YSRQaGVubykpCnBoZW5vX3BhaXJzX2xpc3QgPC0gY29tYm4ocGhlbm90eXBlcywgMiwgc2ltcGxpZnkgPSBGQUxTRSkKYGBgCgoKIyMjIERlZmluZSBjb2xvciBwYWxldHRlcwpgYGB7cn0KbXlfY29sb3JzIDwtIGMoCiAgIiNFNDFBMUMiLCAjIHN0cm9uZyByZWQKICAiIzM3N0VCOCIsICMgbWVkaXVtIGJsdWUKICAiIzREQUY0QSIsICMgZ3JlZW4KICAiIzk4NEVBMyIsICMgcHVycGxlCiAgIiNGRjdGMDAiLCAjIG9yYW5nZQogICIjRkZGRjMzIiwgIyB5ZWxsb3cKICAiI0E2NTYyOCIsICMgYnJvd24KICAiI2U3Mjk4YSIsICMgcGluawogICIjNjY2NjY2IiwgIyBncmV5CiAgIiM2NkMyQTUiLCAjIHRlYWwKICAiI0ZDOEQ2MiIsICMgc2FsbW9uCiAgIiM4REEwQ0IiLCAjIHNvZnQgYmx1ZQogICIjRTc4QUMzIiwgIyBzb2Z0IHBpbmsgKGRpZmZlcmVudCBmcm9tIDgpCiAgIiNBNkQ4NTQiLCAjIGxpZ2h0IGdyZWVuIChidXQgeWVsbG93aXNoIHRpbnQsIG5vdCBncmVlbikKICAiI0ZGRDkyRiIsICMgbGVtb24geWVsbG93CiAgIiNFNUM0OTQiLCAjIGxpZ2h0IGJyb3duCiAgIiNCM0IzQjMiLCAjIGxpZ2h0IGdyZXkKICAiIzFCOUU3NyIsICMgZGVlcCB0ZWFsCiAgIiNEOTVGMDIiLCAjIGRhcmsgb3JhbmdlCiAgIiM3NTcwQjMiLCAjIHN0cm9uZyBwdXJwbGUKICAiIzY2QTYxRSIgICMgb2xpdmUgZ3JlZW4gKE5PVCBzYW1lIGdyZWVuIGFzIGJlZm9yZSkKKQoKYGBgCiMjIyMgRGVmaW5lIGZ1bmN0aW9uIHRvIHBsb3QgdmlvbGluIHBsb3RzIGJ5IHBoZW5vdHlwZQpDb3BpZWQgZnJvbSBbMDJfV1RfUlBNX09yZ2Fub2lkc19BbGxvZ3JhZnRzX25vdGVib29rLlJtZF0oMDJfV1RfUlBNX09yZ2Fub2lkc19BbGxvZ3JhZnRzX25vdGVib29rLlJtZCkgIAoKTmVlZHMgU2luZ2xlQ2VsbEV4cGVyaW1lbnQgYHNjZWAgb2JqZWN0IGFuZCBgcGhlbm9fcGFpcnNfbGlzdGAgZGVmaW5lZCBpbiB0aGUgbm90ZWJvb2suCmBgYHtyfQpwbG90VmxuQnlQaGVuIDwtIGZ1bmN0aW9uKGZlYXR1cmUsIHlsPWMoLTAuMSwwLjMpLCBmb2N1cz1OQSkgewogICAgaWYoIWlzLm5hKGZvY3VzKSkgewogICAgICAgIHBoZW5vX3BhaXJzX2xpc3QgPC0gcGhlbm9fcGFpcnNfbGlzdFtzYXBwbHkocGhlbm9fcGFpcnNfbGlzdCwgZnVuY3Rpb24oeCkgZm9jdXMgJWluJSB4KV0KICAgIH0KICAgIAogICAgc2NhdGVyOjpwbG90Q29sRGF0YShzY2UsIHggPSAiUGhlbm8iLCB5ID0gZmVhdHVyZSwgY29sb3VyX2J5ID0gIlBoZW5vIikgKyAKICAgICAgICBzY2FsZV9kaXNjcmV0ZV9tYW51YWwoYWVzdGhldGljcyA9IGMoImNvbG91ciIsICJmaWxsIiksIHZhbHVlcz1waGVub19jb2wpICsKICAgICAgICB0aGVtZShheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDI0KSwgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwKICAgICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwgICAjIHJvdGF0ZSB4LWF4aXMgbGFiZWxzCiAgICAgICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwgICAgIyByZW1vdmUgcGxvdCB0aXRsZQogICAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiAgICAgICAgICMgcmVtb3ZlIGxlZ2VuZAogICAgICAgICkgKyBsYWJzKHggPSAiIiwgICAgICAgICAgICAgICAgICAgICAjIGN1c3RvbSB4LWF4aXMgdGl0bGUKICAgICAgICAgICAgICAgICB5ID0gIlNpZ25hdHVyZSBzY29yZSIgICAgICAgICMgY3VzdG9tIHktYXhpcyB0aXRsZQogICAgICAgICkgKyB5bGltKHlsWzFdLCB5bFsyXSkgKyAKICAgICAgICBnZW9tX2JveHBsb3QoZmlsbD1waGVub19jb2wsIGFscGhhPTEvNSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IC4yKSwKICAgICAgICAgICAgICAgICAgICAgc2l6ZT0wLjIsIGNvbG9yPSJibGFjayIsIG5vdGNoPVRSVUUsIG5vdGNod2lkdGg9MC4zLCBvdXRsaWVyLnNoYXBlID0gMiwgb3V0bGllci5jb2xvdXI9TkEpICMgKyAKICAgICAgICAjIHN0YXRfc3VtbWFyeShmdW4gPSBtZWFuLAogICAgICAgICMgICAgICAgICAgICAgIGdlb20gPSAicG9pbnQiLAogICAgICAgICMgICAgICAgICAgICAgIHNoYXBlID0gMTgsCiAgICAgICAgIyAgICAgICAgICAgICAgc2l6ZSA9IDIsCiAgICAgICAgIyAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwKICAgICAgICAjICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC41KSkgKyAKICAgICAgICAjIGdncHVicjo6c3RhdF9jb21wYXJlX21lYW5zKG1ldGhvZCA9ICJ3aWxjb3gudGVzdCIsIGxhYmVsID0gInAuc2lnbmlmIiwgc2l6ZT00LCAKICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZqdXN0ID0gMC41LAogICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGlkZS5ucyA9IFRSVUUsIGNvbXBhcmlzb25zID0gcGhlbm9fcGFpcnNfbGlzdCkKfQpgYGAKCiMjIyBGaWcuIDJlIFVNQVAKYGBge3IgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9NywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KRGltUGxvdChUQk9fc2V1cmF0LCBncm91cC5ieT0nR2Vub3R5cGUnLCBjb2xzPWMoImRhcmtvcmNoaWQ0Iiwib3JhbmdlIiksCiAgICAgICAgcHQuc2l6ZSA9IDAuMSwKICAgICAgICByZWR1Y3Rpb249J3VtYXAnLCBsYWJlbD1GQUxTRSwgbGFiZWwuc2l6ZT03LCBzaHVmZmxlPVRSVUUpICYgTm9BeGVzKCkKCmBgYAoKIyMjIEZpZy4gMmYgKFVNQVAgYnkgTGVpZGVuIGNsdXN0ZXIpCmBgYHtyIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTYsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CkRpbVBsb3QoVEJPX3NldXJhdCwgZ3JvdXAuYnk9J2xlaWRlbl9zY1ZJXzEuMicsIAogICAgICAgIGNvbHM9bXlfY29sb3JzLCByZWR1Y3Rpb249J3VtYXAnLCBsYWJlbD1UUlVFLCBsYWJlbC5zaXplPTUsCiAgICAgICAgcHQuc2l6ZSA9IDAuMSkgJiBOb0F4ZXMoKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQoKYGBgCgoKYGBge3IgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CklkZW50cyhUQk9fc2V1cmF0KSA8LSAnbGVpZGVuX3NjVklfMS4yJwoKeCA8LSB0YWJsZShUQk9fc2V1cmF0QG1ldGEuZGF0YSRHZW5vdHlwZSxJZGVudHMoVEJPX3NldXJhdCkpCnByb3BvcnRpb25zIDwtIGFzLmRhdGEuZnJhbWUoMTAwKnByb3AudGFibGUoeCwgbWFyZ2luID0gMSkpCgpjb2xuYW1lcyhwcm9wb3J0aW9ucykgPC0gYygiU2FtcGxlIiwgIkNsdXN0ZXIiLCAiRnJlcXVlbmN5IikKCiMgZ2dwdWJyOjpnZ2JhcnBsb3QocHJvcG9ydGlvbnMsIHg9IlNhbXBsZSIsIHk9IkZyZXF1ZW5jeSIsIGZpbGwgPSAiU2FtcGxlIiwgZ3JvdXAgPSAiU2FtcGxlIiwKIyAgICAgICAgICAgICAgICAgICB5bGFiID0gIkZyZXF1ZW5jeSAocGVyY2VudCkiLCB4bGFiPSJQaGFzZSIsIHBhbGV0dGUgPWMoImluZGlhbnJlZDMiLCJncmVlbjMiLCJyb3lhbGJsdWU0IikpICsKIyAgICAgdGhlbWVfYncoKSArIGZhY2V0X3dyYXAoZmFjZXRzID0gIkNsdXN0ZXIiLCBzY2FsZXM9ImZyZWVfeSIsIG5jb2wgPTQpICsKIyAgICAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT02KSkgKyBnZ3B1YnI6OnJvdGF0ZV94X3RleHQoYW5nbGUgPSA0NSkKYGBgCgojIyMjIEZpZyAyZgpgYGB7ciBmaWcuaGVpZ2h0PTMuNSwgZmlnLndpZHRoPTMuNSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBTdGFja2VkCnAgPC0gZ2dwbG90KHByb3BvcnRpb25zLCBhZXMoZmlsbD1DbHVzdGVyLCB5PUZyZXF1ZW5jeSwgeD1TYW1wbGUpKSArIAogICAgZ2VvbV9iYXIocG9zaXRpb249InN0YWNrIiwgc3RhdD0iaWRlbnRpdHkiKQoKcCArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1teV9jb2xvcnMpICsgdGhlbWVfYncoKSArIAogICAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksIAogICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNiwgYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUsIGhqdXN0PTEpLCAKICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemU9MTYpLCAKICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTIpLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpICsgCiAgICBsYWJzKHggPSBOVUxMLCB5ID0gIlNhbXBsZSBjb21wb3NpdGlvbiAoJSkiKQpgYGAKCiMjIyBGaWcuIDJoIApVTUFQIGNvbG9yZWQgYnkgU0NMQyBmYXRlCmBgYHtyIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTcsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgRGVmaW5lIGZhdGUgY29sb3IgdmVjdG9yIGFuZCB1c2UgdG8gcGxvdCBieSBjZWxsIHN0YXRlCnBoZW5vX2NvbCA8LSBjKCJicm93bjIiLCJkYXJrb3JjaGlkNCIsImRvZGdlcmJsdWUiLCIjNjZBNjFFIiwib3JhbmdlIiwidHVycXVvaXNlNCIsInR1cnF1b2lzZSIpCkRpbVBsb3QoVEJPX3NldXJhdCwgZ3JvdXAuYnk9J1BoZW5vJywgY29scz1waGVub19jb2wsIHJlZHVjdGlvbj0ndW1hcCcsIGxhYmVsPUZBTFNFLCAKICAgICAgICBzaHVmZmxlPVRSVUUsIGxhYmVsLnNpemU9NikgJiBOb0F4ZXMoKQoKYGBgCiMjIyMgRmlnLiAyaCAoc3RhY2tlZCBiYXJwbG90IGJ5IFBoZW5vKQoKYGBge3IgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9NCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KSWRlbnRzKFRCT19zZXVyYXQpIDwtJ1BoZW5vJwoKeCA8LSB0YWJsZShUQk9fc2V1cmF0QG1ldGEuZGF0YSRHZW5vdHlwZSxJZGVudHMoVEJPX3NldXJhdCkpCnByb3BvcnRpb25zIDwtIGFzLmRhdGEuZnJhbWUoMTAwKnByb3AudGFibGUoeCwgbWFyZ2luID0gMSkpCgpjb2xuYW1lcyhwcm9wb3J0aW9ucyk8LWMoIkNsdXN0ZXIiLCAiU2FtcGxlIiwgIkZyZXF1ZW5jeSIpCgpwIDwtIGdncGxvdChwcm9wb3J0aW9ucywgYWVzKGZpbGw9U2FtcGxlLCB5PUZyZXF1ZW5jeSwgeD1DbHVzdGVyKSkgKyAKICAgIGdlb21fYmFyKHBvc2l0aW9uPSJzdGFjayIsIHN0YXQ9ImlkZW50aXR5IikKCnAgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9cGhlbm9fY29sKSArIHRoZW1lX2J3KCkgKyAKICAgIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MjApLCAKICAgICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChzaXplPTIwLCBhbmdsZSA9IDkwLCBoanVzdCA9IDEsIHZqdXN0ID0gMC41KSwgCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0yMCksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTIwKSwgCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTIwKSwgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MjApKSArIAogICAgbGFicyh4ID0gTlVMTCkKYGBgCgojIyMjIEZpZy4gMmkgVU1BUApORSBzY29yZSAoY29ycmVsYXRpb24pCmBgYHtyIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTMuNSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KRmVhdHVyZVBsb3QoVEJPX3NldXJhdCwgZmVhdHVyZXMgPSBjKCJORV9zcGVhcm1hbiIpLCBwdC5zaXplPTAuMiwKICAgICAgICAgICAgcmVkdWN0aW9uPSd1bWFwJykgKyB2aXJpZGlzOjpzY2FsZV9jb2xvcl92aXJpZGlzKG9wdGlvbj0icm9ja2V0IixkaXJlY3Rpb249LTEpICYgTm9BeGVzKCkKYGBgCgojIyMjIEZpZyAyaSAodmlvbGluIHBsb3RzIG9mIE5FIHNjb3JlIGJ5IFNDTEMgZmF0ZSkKYGBge3IgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9MywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcGxvdFZsbkJ5UGhlbigiTkVfc3BlYXJtYW4iLCB5bD1jKC0uNywgLjgpKQpgYGAKCiMjIyMgRmlnIDJpICh2aW9saW4gcGxvdHMgb2YgTkUgc2NvcmUgYnkgZ2Vub3R5cGUpCmBgYHtyIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnggPC0gc2NhdGVyOjpwbG90Q29sRGF0YShzY2UsIHggPSAiR2Vub3R5cGUiLCB5ID0gIk5FX3NwZWFybWFuIiwgY29sb3VyX2J5ID0gIkdlbm90eXBlIikgKyAKICAgIHNjYWxlX2Rpc2NyZXRlX21hbnVhbChhZXN0aGV0aWNzID0gYygiY29sb3VyIiwgImZpbGwiKSwgdmFsdWVzPWMoImRhcmtvcmNoaWQ0Iiwib3JhbmdlIikpCgp4IDwtIHggKyB0aGVtZShheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDI0KSxheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLCAKICAgICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgICAgICAgICAjIHBsb3QudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyBsYWJzKHggPSAiIiwgIHkgPSAiU2lnbmF0dXJlIHNjb3JlIikgKyAgeWxpbSgtMSwxKSArIAogICAgZ2VvbV9ib3hwbG90KGZpbGw9YygiZGFya29yY2hpZDQiLCJvcmFuZ2UiKSwgYWxwaGE9MS81LCAKICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gLjIpLCBzaXplPTAuMiwKICAgICAgICAgICAgICAgICBjb2xvcj0iYmxhY2siLCBub3RjaD1UUlVFLCBub3RjaHdpZHRoPTAuMywgb3V0bGllci5zaGFwZSA9IDIsIG91dGxpZXIuY29sb3VyPU5BKQoKIyMgUGVyZm9ybSB3aWxjb3hvbiByYW5rLXN1bSB0ZXN0IGZvciBSUE0gdnMgUlBNQSBvbiB0aGUgTkUgc2NvcmUgZGF0YSAoRmlnLiAzaSkgIyMKeCArIHN0YXRfc3VtbWFyeShmdW4gPSBtZWFuLAogICAgICAgICAgICAgICAgIGdlb20gPSAicG9pbnQiLAogICAgICAgICAgICAgICAgIHNoYXBlID0gMTgsCiAgICAgICAgICAgICAgICAgc2l6ZSA9IDIsCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwKICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC45KSkgKyAKICAgIGdncHVicjo6c3RhdF9jb21wYXJlX21lYW5zKG1ldGhvZCA9ICJ3aWxjb3gudGVzdCIsbGFiZWwgPSAicC5zaWduaWYiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhpZGUubnMgPSBUUlVFLGNvbXBhcmlzb25zID0gbGlzdChjKCJSUE0iLCAiUlBNQSIpKSkKCmBgYAoKCiMjIyBGaWcuIDJqIAojIyMjIEZpZyAyaiAoVU1BUCBtYXJrZXIgZ2VuZSBleHByZXNzaW9uKQpFcXVpdmFsZW50IGNvbG9yIHNjaGVtZXM6ICAKKiBgdmlyaWRpczo6c2NhbGVfY29sb3JfdmlyaWRpcyhvcHRpb249InJvY2tldCIsIGRpcmVjdGlvbj0tMSlgICAKKiBgc2NhbGVfY29sb3JfZ3JhZGllbnRuKGNvbG9ycz12aXJpZGlzOjpyb2NrZXQoMTAsIGRpcmVjdGlvbj0tMSkpYAoKCmBgYHtyIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTQsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgVEYgdGFyZ2V0IGdlbmUgc2NvcmVzIGluIFVNQVAKRmVhdHVyZVBsb3QoVEJPX3NldXJhdCwgZmVhdHVyZXMgPSBjKCJBU0NMMV9UYXJnZXRzMSIpLCBwdC5zaXplPTAuMiwgCiAgICAgICAgICAgIHJlZHVjdGlvbj0ndW1hcCcpICsgdmlyaWRpczo6c2NhbGVfY29sb3JfdmlyaWRpcyhvcHRpb249InJvY2tldCIsZGlyZWN0aW9uPS0xKSAmIE5vQXhlcygpCkZlYXR1cmVQbG90KFRCT19zZXVyYXQsIGZlYXR1cmVzID0gYygiTkVVUk9EMV9UYXJnZXRzMSIpLCBwdC5zaXplPTAuMiwKICAgICAgICAgICAgcmVkdWN0aW9uPSd1bWFwJykgKyB2aXJpZGlzOjpzY2FsZV9jb2xvcl92aXJpZGlzKG9wdGlvbj0icm9ja2V0IixkaXJlY3Rpb249LTEpICYgTm9BeGVzKCkKRmVhdHVyZVBsb3QoVEJPX3NldXJhdCwgZmVhdHVyZXMgPSBjKCJBVE9IMV9UYXJnZXRzMSIpLCBwdC5zaXplPTAuMiwKICAgICAgICAgICAgcmVkdWN0aW9uPSd1bWFwJykgKyB2aXJpZGlzOjpzY2FsZV9jb2xvcl92aXJpZGlzKG9wdGlvbj0icm9ja2V0IixkaXJlY3Rpb249LTEpICYgTm9BeGVzKCkKRmVhdHVyZVBsb3QoVEJPX3NldXJhdCwgZmVhdHVyZXMgPSBjKCJQT1UyRjNfVGFyZ2V0czEiKSwgcHQuc2l6ZT0wLjIsCiAgICAgICAgICAgIHJlZHVjdGlvbj0ndW1hcCcpICsgdmlyaWRpczo6c2NhbGVfY29sb3JfdmlyaWRpcyhvcHRpb249InJvY2tldCIsZGlyZWN0aW9uPS0xKSAmIE5vQXhlcygpCkZlYXR1cmVQbG90KFRCT19zZXVyYXQsIGZlYXR1cmVzID0gYygiWUFQX0FjdGl2aXR5MSIpLCBwdC5zaXplPTAuMiwKICAgICAgICAgICAgcmVkdWN0aW9uPSd1bWFwJykgKyB2aXJpZGlzOjpzY2FsZV9jb2xvcl92aXJpZGlzKG9wdGlvbj0icm9ja2V0IixkaXJlY3Rpb249LTEpICYgTm9BeGVzKCkKCmBgYAoKCiMjIyBWbG5QbG90cyBieSBnZW5vdHlwZSB3aXRoIHdpbGNveG9uIHJhbmsgc3VtIHRlc3RzCiMjIyMgRmlnLiAyaiAodmlvbGluIHBsb3RzKQpgYGB7cn0KcGxvdFRGc2NvcmVzVmxuIDwtIGZ1bmN0aW9uKHNjb3JlX25hbWUsIHlsPWMoLS4xLCAuMzIpKSB7CiAgICBhIDwtIFZsblBsb3QoVEJPX3NldXJhdCwKICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9IGMoc2NvcmVfbmFtZSksCiAgICAgICAgICAgICAgICAgZ3JvdXAuYnkgPSAiR2Vub3R5cGUiLAogICAgICAgICAgICAgICAgIGNvbHMgPSBjKCJkYXJrb3JjaGlkNCIsICJvcmFuZ2UiKSwKICAgICAgICAgICAgICAgICBwdC5zaXplID0gMC4wMSwKICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuMDUsCiAgICAgICAgICAgICAgICAgbmNvbCA9IDEpICsgCiAgICAgICAgdGhlbWUoYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCksCiAgICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwLCBoanVzdCA9IDAuNSwgc2l6ZT0yMCksICAjIHJvdGF0ZSB4LWF4aXMgbGFiZWxzCiAgICAgICAgICAgICAgIyBwbG90LnRpdGxlID0gZWxlbWVudF9ibGFuaygpLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgcmVtb3ZlIHBsb3QgdGl0bGUKICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgcmVtb3ZlIGxlZ2VuZAogICAgICAgICkgKyAKICAgICAgICBsYWJzKHggPSAiIiwgICAgICAgICAgICAgIyBjdXN0b20geC1heGlzIHRpdGxlCiAgICAgICAgICAgICB5ID0gIkV4cHJlc3Npb24iICAjIGN1c3RvbSB5LWF4aXMgdGl0bGUKICAgICAgICApICsgeWxpbSh5bFsxXSwgeWxbMl0pICsgCiAgICAgICAgc3RhdF9zdW1tYXJ5KGZ1biA9IG1lYW4sCiAgICAgICAgICAgICAgICAgICAgIGdlb20gPSAicG9pbnQiLAogICAgICAgICAgICAgICAgICAgICBzaGFwZSA9IDE4LAogICAgICAgICAgICAgICAgICAgICBzaXplID0gMiwKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwKICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOSkpICsgCiAgICAgICAgZ2dwdWJyOjpzdGF0X2NvbXBhcmVfbWVhbnMobWV0aG9kID0gIndpbGNveC50ZXN0IiwgbGFiZWwgPSAicC5zaWduaWYiLCBzaXplPTgsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhpZGUubnMgPSBUUlVFLCBjb21wYXJpc29ucyA9IGxpc3QoYygiUlBNIiwgIlJQTUEiKSkpCiAgICAgICAgCiAgICAgICAgIyBBZGQgbWVhbiBwb2ludCBhbmQgZG8gd2lsY294b24gcmFuayBzdW0gdGVzdCAKICAgIHJldHVybihhKQp9CmBgYAojIyMjIEZpZyAyaiAoaW5zZXRzKQpgYGB7ciBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD0zLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwbG90VEZzY29yZXNWbG4oIkFUT0gxX1RhcmdldHMxIikKcGxvdFRGc2NvcmVzVmxuKCJBU0NMMV9UYXJnZXRzMSIsIHlsPWMoLTAuMSwgMC44KSkKcGxvdFRGc2NvcmVzVmxuKCJORVVST0QxX1RhcmdldHMxIikKcGxvdFRGc2NvcmVzVmxuKCJQT1UyRjNfVGFyZ2V0czEiKQpwbG90VEZzY29yZXNWbG4oIllBUF9BY3Rpdml0eTEiLCB5bD1jKC0wLjEsIDEpKQpgYGAKCiMjIyBGaWcuIDJrIChVTUFQIGJ5IGNlbGwgdHlwZSBjb25zZW5zdXMgc2lnbmF0dXJlKQpgYGB7ciBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD00LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpGZWF0dXJlUGxvdChUQk9fc2V1cmF0LCBmZWF0dXJlcyA9IGMoIk5FX0NvbnNlbnN1czEiKSwgcHQuc2l6ZT0wLjIsIAogICAgICAgICAgICByZWR1Y3Rpb249J3VtYXAnKSArIHZpcmlkaXM6OnNjYWxlX2NvbG9yX3ZpcmlkaXMob3B0aW9uPSJyb2NrZXQiLGRpcmVjdGlvbj0tMSkgJiBOb0F4ZXMoKQpGZWF0dXJlUGxvdChUQk9fc2V1cmF0LCBmZWF0dXJlcyA9IGMoIkJhc2FsX0NvbnNlbnN1czEiKSwgcHQuc2l6ZT0wLjIsCiAgICAgICAgICAgIHJlZHVjdGlvbj0ndW1hcCcpICsgdmlyaWRpczo6c2NhbGVfY29sb3JfdmlyaWRpcyhvcHRpb249InJvY2tldCIsZGlyZWN0aW9uPS0xKSAmIE5vQXhlcygpCkZlYXR1cmVQbG90KFRCT19zZXVyYXQsIGZlYXR1cmVzID0gYygiVHVmdF9Db25zZW5zdXMxIiksIHB0LnNpemU9MC4yLAogICAgICAgICAgICByZWR1Y3Rpb249J3VtYXAnKSArIHZpcmlkaXM6OnNjYWxlX2NvbG9yX3ZpcmlkaXMob3B0aW9uPSJyb2NrZXQiLGRpcmVjdGlvbj0tMSkgJiBOb0F4ZXMoKQpgYGAKCiMjIyBGaWcuIDJrICh2aW9saW4gcGxvdHMgb2YgY29uc2Vuc3VzIHNpZ25hdHVyZXMgYnkgU0NMQyBmYXRlKQpgYGB7ciBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD0zLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwbG90VmxuQnlQaGVuKCJORV9Db25zZW5zdXMxIiwgeWw9YygtMC41LCAxLjMpKQpwbG90VmxuQnlQaGVuKCJUdWZ0X0NvbnNlbnN1czEiLCB5bD1jKC0wLjI1LCAxKSkKcGxvdFZsbkJ5UGhlbigiQmFzYWxfQ29uc2Vuc3VzMSIsIHlsPWMoLTAuMSwgMS4xKSkKYGBgCiMjIyMgRmlnIDJsICh2aW9saW4gcGxvdHMgb2YgU0NMQyBhcmhjZXR5cGUgc2NvcmVzIGJ5IHBoZW5vdHlwZSkKYGBge3IgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9MywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcGxvdFZsbkJ5UGhlbigiQV9BcmNoZXR5cGUxIiwgeWw9YygtMC4wNSwgMC4yNykpCnBsb3RWbG5CeVBoZW4oIkEyX0FyY2hldHlwZTEiLCB5bD1jKC0wLjA1LCAwLjIpKQpwbG90VmxuQnlQaGVuKCJOX0FyY2hldHlwZTEiLCB5bD1jKDAsIDAuMykpCnBsb3RWbG5CeVBoZW4oIlBfQXJjaGV0eXBlMSIsIHlsPWMoMCwgMC4yNykpCmBgYAoKIyMjIyBFeHQgRGF0YSBGaWcgNWMKYGBge3J9CnBsb3RTdGFja2VkQmFyQnlHZW5vIDwtIGZ1bmN0aW9uKGdlbmUsIGxhYikgewogICAgZGF0IDwtIEZldGNoRGF0YShUQk9fc2V1cmF0LCB2YXJzID0gYyhnZW5lLCAiR2Vub3R5cGUiKSkKICAgIGRhdCA8LSBkYXQgJT4lCiAgICAgIG11dGF0ZShFeHByZXNzaW9uX1N0YXR1cyA9IGlmZWxzZShkYXRbLGdlbmVdID4gMC4wMSwgIlBvc2l0aXZlIiwgIk5lZ2F0aXZlIikpCiAgICAKICAgIHggPC0gdGFibGUoZGF0JEdlbm90eXBlLCBkYXQkRXhwcmVzc2lvbl9TdGF0dXMpCiAgICAKICAgIHByb3BvcnRpb25zIDwtIGFzLmRhdGEuZnJhbWUocHJvcC50YWJsZSh4LCBtYXJnaW4gPSAxKSkKICAgIGNvbG5hbWVzKHByb3BvcnRpb25zKSA8LSBjKCJDbHVzdGVyIiwgIlNhbXBsZSIsICJGcmFjdGlvbiIpCgogICAgcCA8LSBnZ3Bsb3QocHJvcG9ydGlvbnMsIGFlcyhmaWxsID0gU2FtcGxlLCB5ID0gRnJhY3Rpb24sIHggPSBDbHVzdGVyKSkgKyAKICAgICAgICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJzdGFjayIsIHN0YXQgPSAiaWRlbnRpdHkiKQogICAgcCA8LSBwICsgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoImJsdWU0IiwicmVkMyIpKSsgdGhlbWVfYncoKSArIAogICAgICAgIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MjApLCBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT0yMCksIAogICAgICAgICAgICAgIGF4aXMudGl0bGUueCA9ZWxlbWVudF90ZXh0KHNpemU9MjApLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0yMCksIAogICAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MjApLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0wKSwgCiAgICAgICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTgsIGZhY2UgPSAicGxhaW4iLCBoanVzdCA9IDAuNSkpICsgCiAgICAgICAgbGFicyh5ID0gbGFiLCB4ID0gTlVMTCkKICAgIHJldHVybihwKQp9CmBgYAoKYGBge3IgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9NiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcGxvdFN0YWNrZWRCYXJCeUdlbm8oIkFzY2wxIiwgIkZyYWN0aW9uIG9mIEFzY2wxLWhpIGNlbGxzICg+MC4wMSkiKQpwbG90U3RhY2tlZEJhckJ5R2VubygiTmV1cm9kMSIsICJGcmFjdGlvbiBvZiBOZXVyb2QxLWhpIGNlbGxzICg+MC4wMSkiKQpwbG90U3RhY2tlZEJhckJ5R2VubygiUG91MmYzIiwgIkZyYWN0aW9uIG9mIFBvdTJmMy1oaSBjZWxscyAoPjAuMDEpIikKYGBgCgoKCiMjIyBFeHRlbmRlZCBEYXRhIEZpZy4gNWUKVmlvbGluIHBsb3RzIG9mIGV4cHJlc3Npb24gb2YgVEZzIGJ5IExlaWRlbiBjbHVzdGVyCmBgYHtyIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTEwLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpnZW5lcyA8LSBjKCJBc2NsMSIsIk5ldXJvZDEiLCJQb3UyZjMiKQoKIyBDcmVhdGUgdmlvbGluIHBsb3RzIHdpdGggS3J1c2thbC1XYWxsaXMgdGVzdApwbG90cyA8LSBsYXBwbHkoZ2VuZXMsIGZ1bmN0aW9uKGdlbmUpIHsKICBwIDwtIFZsblBsb3QoVEJPX3NldXJhdCwKICAgICAgICAgICAgICAgZmVhdHVyZXMgPSBnZW5lLAogICAgICAgICAgICAgICBncm91cC5ieSA9ICJsZWlkZW5fc2NWSV8xLjIiLAogICAgICAgICAgICAgICBjb2xzID0gbXlfY29sb3JzLAogICAgICAgICAgICAgICBhbHBoYSA9IDAuNSkgKyAgIyBzbWFsbGVyIGRvdHMKICAgIGdncHVicjo6c3RhdF9jb21wYXJlX21lYW5zKG1ldGhvZCA9ICJrcnVza2FsLnRlc3QiLCAKICAgICAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICJwLmZvcm1hdCIsIAogICAgICAgICAgICAgICAgICAgICAgIGxhYmVsLnggPSAyLHNpemUgPSA1KSArCiAgICBnZ3RpdGxlKCIiKSArCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiaXRhbGljIiksIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgICMgUmVtb3ZlIGxlZ2VuZAogICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjApLAogICAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkgKyAgIyBSZW1vdmUgeC1heGlzIGxhYmVsCiAgICBsYWJzKHkgPSAiRXhwcmVzc2lvbiIpICAjIENoYW5nZSB5LWF4aXMgbGFiZWwgdG8gIkV4cHJlc3Npb24iCiAgcmV0dXJuKHApCn0pCgojIEFycmFuZ2UgcGxvdHMKcGF0Y2h3b3JrOjp3cmFwX3Bsb3RzKHBsb3RzLCBuY29sID0gMykKYGBgCgoKIyMjIyBFeHQgRGF0YSBGaWcgMTAKYGBge3IgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KRmVhdHVyZVBsb3QoVEJPX3NldXJhdCwgZmVhdHVyZXMgPSBjKCJJb25vX01vdXNlX0V4dDEiKSwgcHQuc2l6ZT0wLjIsCiAgICAgICAgICAgIHJlZHVjdGlvbj0ndW1hcCcpICsgdmlyaWRpczo6c2NhbGVfY29sb3JfdmlyaWRpcyhvcHRpb249InJvY2tldCIsZGlyZWN0aW9uPS0xKSAmIE5vQXhlcygpCkZlYXR1cmVQbG90KFRCT19zZXVyYXQsIGZlYXR1cmVzID0gYygiSW9ub19IdW1hbjEiKSwgcHQuc2l6ZT0wLjIsCiAgICAgICAgICAgIHJlZHVjdGlvbj0ndW1hcCcpICsgdmlyaWRpczo6c2NhbGVfY29sb3JfdmlyaWRpcyhvcHRpb249InJvY2tldCIsZGlyZWN0aW9uPS0xKSAmIE5vQXhlcygpCmBgYAoKCiMjIyBFeHQgRGF0YSBGaWcuIDEwZSAodmlvbGluIHBsb3RzIG9mIGNvbnNlbnN1cyBzaWduYXR1cmVzIGJ5IFNDTEMgZmF0ZSkKYGBge3IgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9MywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcGxvdFZsbkJ5UGhlbigiSW9ub19Nb3VzZV9FeHQxIiwgeWw9YygtMC4xLCAwLjQ1KSkKcGxvdFZsbkJ5UGhlbigiSW9ub19IdW1hbjEiLCB5bD1jKC0wLjEsIC43NSkpCmBgYAoKIyMjIyBGaWcgNWQKQ2FyaXMgU0NMQyB0dW1vciBzaWduYXR1cmVzIGluIGJhc2FsIGNlbGxzCmBgYHtyIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTQsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmNhcmlzX2ZlYXQgPC0gIGMoIkNhcmlzX0ExIiwiQ2FyaXNfWTEiLCJDYXJpc19OMSIsIkNhcmlzX01peGVkMSIsIkNhcmlzX1AxIiwiQ2FyaXNfVE4tMSIpCgp2IDwtIEZlYXR1cmVQbG90KFRCT19zZXVyYXQsIGZlYXR1cmVzID0gY2FyaXNfZmVhdCwgcHQuc2l6ZT0wLjIsIHJlZHVjdGlvbj0ndW1hcCcpIAp2IDwtIGxhcHBseSh2LCBgK2AsIHNjYWxlX2NvbG9yX3ZpcmlkaXMob3B0aW9uPSJyb2NrZXQiLCBkaXJlY3Rpb249LTEpKQpsYXBwbHkodiwgYCtgLCBOb0F4ZXMoKSkKYGBgCgoKIyMjIyBGaWcgNWQgKHZpb2xpbiBwbG90cyBvZiBodW1hbiB0dW1vciBTQ0xDIHNjb3JlcyBieSBTQ0xDIGZhdGUpCmBgYHtyIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTMuNSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcGxvdFZsbkJ5UGhlbigiQ2FyaXNfQTEiLCB5bD1jKC0wLjEsIDAuMikpCnBsb3RWbG5CeVBoZW4oIkNhcmlzX1kxIiwgeWw9YygtMC4xLCAwLjIpKQpwbG90VmxuQnlQaGVuKCJDYXJpc19OMSIsIHlsPWMoLTAuMSwgMC4zKSkKcGxvdFZsbkJ5UGhlbigiQ2FyaXNfTWl4ZWQxIiwgeWw9YygtMC4xLCAwLjE1KSkKcGxvdFZsbkJ5UGhlbigiQ2FyaXNfUDEiLCB5bD1jKC0wLjEsIDAuMjUpKQpwbG90VmxuQnlQaGVuKCJDYXJpc19UTi4xIiwgeWw9YygtMC4xLCAwLjI1KSkKYGBgCgoKCiMjIyMgRmlnLiA1ZQpHZW5lIHNpZ25hdHVyZSBzY29yZXMgY29ycmVsYXRpb24gaGVhdG1hcApgYGB7ciBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD05fQpzaWduYXR1cmVfbWF0cml4IDwtIEZldGNoRGF0YShUQk9fc2V1cmF0LCB2YXJzID0gYygiQ2FyaXNfQTEiLCAiR2VvcmdlX0ExIiwgIkxpdV9BMSIsIkxpc3NhX0ExIiwiQVNDTDFfVGFyZ2V0czEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ2FyaXNfTjEiLCJHZW9yZ2VfTjEiLCAiTGl1X04xIiwiTGlzc2FfTjEiLCAiTkVVUk9EMV9UYXJnZXRzMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDYXJpc19QMSIsIkdlb3JnZV9QMSIsICJMaXVfUDEiLCJQT1UyRjNfVGFyZ2V0czEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ2FyaXNfWTEiLCJHZW9yZ2VfWTEiLCAiTGlzc2FfWTEiLCAiWUFQX0FjdGl2aXR5MSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHYXlfU0NMQy1JMSIsIk1IQ19TaWdfR2F5MSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJORV9Db25zZW5zdXMxIiwiQmFzYWxfQ29uc2Vuc3VzMSIsIlR1ZnRfQ29uc2Vuc3VzMSIpKQojIHJlcGxhY2UgR2F5X1NDTEMtSTEgd2l0aCBUX0NlbGxfSW5mbGFtZWRfR2F5MQoKIyBDb21wdXRlIFBlYXJzb24gY29ycmVsYXRpb24gbWF0cml4CmNvcnJlbGF0aW9uX21hdHJpeCA8LSBjb3Ioc2lnbmF0dXJlX21hdHJpeCwgbWV0aG9kID0gInBlYXJzb24iKQoKIyBEZWZpbmUgY29sb3Igc2NhbGUgZnJvbSAtMSB0byAxCmJyZWFrc19zZXEgPC0gc2VxKC0xLCAxLCBsZW5ndGgub3V0ID0gMTAwKSAgIyBFbnN1cmUgc2NhbGUgY292ZXJzIGZ1bGwgY29ycmVsYXRpb24gcmFuZ2UKCnBoZWF0bWFwOjpwaGVhdG1hcChjb3JyZWxhdGlvbl9tYXRyaXgsIAogICAgICAgICBjb2xvciA9IHNjaWNvOjpzY2ljbygxMDAsIHBhbGV0dGUgPSAiYmVybGluIiksCiAgICAgICAgIGRpc3BsYXlfbnVtYmVycyA9IEZBTFNFLCAKICAgICAgICAgYnJlYWtzID0gYnJlYWtzX3NlcSwgbnVtYmVyX2NvbG9yID0gImdyYXk4MCIsZm9udHNpemVfbnVtYmVyPTYsCiAgICAgICAgIG1haW4gPSAiU2lnbmF0dXJlIGNvcnJlbGF0aW9uIGluIG1vdXNlIFRCTyBBbGxvZ3JhZnRzIiwgY2x1c3Rlcl9jb2xzID0gVFJVRSwgY2x1c3Rlcl9yb3dzPVRSVUUpCmBgYAoKIyMjIyBGaWcgNWcKSW5mbGFtbWF0b3J5IHNpZ25hdHVyZXMgaW4gYmFzYWwgY2VsbHMKYGBge3IgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBGaWcgNWcgZmVhdHVyZSBwbG90IChNSENfU2lnX0dheTE9IkFudGlnZW4gcHJlc2VudGF0aW9uIikgIwpGZWF0dXJlUGxvdChUQk9fc2V1cmF0LCBmZWF0dXJlcyA9IGMoIk1IQ19TaWdfR2F5MSIpLCBwdC5zaXplPTAuMiwgCiAgICAgICAgICAgIHJlZHVjdGlvbj0ndW1hcCcpICsgdmlyaWRpczo6c2NhbGVfY29sb3JfdmlyaWRpcyhvcHRpb249InJvY2tldCIsZGlyZWN0aW9uPS0xKSAmIE5vQXhlcygpCgojIyMgTk1GMy1JIHNpZ25hdHVyZSBmb3IgRmlnLiA1ZwpGZWF0dXJlUGxvdChUQk9fc2V1cmF0LCBmZWF0dXJlcyA9IGMoIk5NRjMtSTEiKSwgcHQuc2l6ZT0wLjIsIAogICAgICAgICAgICByZWR1Y3Rpb249J3VtYXAnKSArIHZpcmlkaXM6OnNjYWxlX2NvbG9yX3ZpcmlkaXMob3B0aW9uPSJyb2NrZXQiLGRpcmVjdGlvbj0tMSkgJiBOb0F4ZXMoKQoKIyMjIEdheSBldCBhbCBTQ0xDLUkgc2lnbmF0dXJlIGZvciBGaWcuIDVnCkZlYXR1cmVQbG90KFRCT19zZXVyYXQsIGZlYXR1cmVzID0gYygiR2F5X1NDTEMtSTEiKSwgcHQuc2l6ZT0wLjIsIAogICAgICAgICAgICByZWR1Y3Rpb249J3VtYXAnKSArIHZpcmlkaXM6OnNjYWxlX2NvbG9yX3ZpcmlkaXMob3B0aW9uPSJyb2NrZXQiLGRpcmVjdGlvbj0tMSkgJiBOb0F4ZXMoKQoKYGBgCgoKIyMjIyBGaWcgNWcgKHZpb2xpbiBwbG90cyBvZiBpbmZsYW1tYXRpb24gc2NvcmVzIGJ5IFNDTEMgZmF0ZSkKYGBge3IgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9My41LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwbG90VmxuQnlQaGVuKCJNSENfU2lnX0dheTEiLCB5bD1jKC0wLjEsIDAuOCkpCnBsb3RWbG5CeVBoZW4oIk5NRjMuSTEiLCB5bD1jKC0wLjEsIDAuNSkpCnBsb3RWbG5CeVBoZW4oIkdheV9TQ0xDLkkxIiwgeWw9YygtMC4xLCAwLjMpKQpgYGAKCgojIyMjIEZpZyA1aCAodmlvbGluIHBsb3RzIG9mIHRoZXJhcGV1dGljIHRhcmdldCBnZW5lIGV4cHJlc3Npb24gYnkgU0NMQyBmYXRlKQpgYGB7ciBmaWcuaGVpZ2h0PTIuNSwgZmlnLndpZHRoPTh9CnhfbGFicyA8LSBjKCJBIiwiQS9OIiwiTiIsIkF0IiwiUCIsIlNMIiwiQiIpCgp2IDwtIFZsblBsb3QoVEJPX3NldXJhdCwgZmVhdHVyZXMgPSBjKCJEbGwzIiwgIk5jYW0xIiwgIlNlejYiLCAiVGFjc3RkMiIpLCAKICAgICAgICBncm91cC5ieT1jKCJQaGVubyIpLCBjb2xzPXBoZW5vX2NvbCxhbHBoYT0wLjA1LCBuY29sPTQpCnYgPC0gbGFwcGx5KHYsICBgK2AsIGxhYnMoeD1OVUxMLCB5PSJFeHByZXNzaW9uIikpCnYgPC0gbGFwcGx5KHYsICBgK2AsIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTkwKSkpCnYgPC0gbGFwcGx5KHYsICBgK2AsICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz14X2xhYnMpKQoKcGF0Y2h3b3JrOjp3cmFwX3Bsb3RzKHYsIG5jb2w9NCkKYGBgCiMjIyMgRXh0IERhdGEgRmlnIDZhCmBgYHtyIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTV9CkRpbVBsb3QoVEJPX3NldXJhdCwgZ3JvdXAuYnk9J0dlbm9DVCcsIGNvbHM9bXlfY29sb3JzLCBzaHVmZmxlPVRSVUUsIAogICAgICAgIHJlZHVjdGlvbj0ndW1hcCcsIGxhYmVsPUZBTFNFLCBsYWJlbC5zaXplPTYpICYgTm9BeGVzKCkgKyBOb0xlZ2VuZCgpCkRpbVBsb3QoVEJPX3NldXJhdCwgZ3JvdXAuYnk9J0dlbm9DVCcsIGNvbHM9bXlfY29sb3JzLCBzaHVmZmxlPVRSVUUsIAogICAgICAgIHJlZHVjdGlvbj0nZmEnLCBsYWJlbD1GQUxTRSwgbGFiZWwuc2l6ZT02KSAmIE5vQXhlcygpICsgTm9MZWdlbmQoKQpgYGAKCgojIyMgQ2VsbFRhZyBhbmFseXNpcyBpbiBvdGhlciBub3RlYm9vawo=